package sifeap.bl.ejb.solicitudescredito;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import sifeap.bridge.AportesBridge;
import sifeap.bridge.CreditosBridge;
import sifeap.bridge.VinculadosBridge;
import sifeap.dal.ejb.solicitudescredito.CodeudorDALLocal;
import sifeap.dal.ejb.solicitudescredito.EstadoCreditoDALLocal;
import sifeap.dal.ejb.solicitudescredito.SolicitudCreditoDALLocal;
import sifeap.dal.ejb.solicitudescredito.TipoCreditoDALLocal;
import sifeap.dal.ejb.soportes.SoporteDALLocal;
import sifeap.entities.solicitudescredito.Codeudor;
import sifeap.entities.solicitudescredito.EstadoCredito;
import sifeap.entities.solicitudescredito.SolicitudCredito;
import sifeap.entities.solicitudescredito.TipoCredito;
import sifeap.entities.solicitudescredito.valueobject.SolicitudCreditoVO;
import sifeap.entities.soportes.Soporte;
import sifeap.exception.SifeapException;
import sifeap.wrappers.aportes.AporteWrapper;
import sifeap.wrappers.asociados.VinculadoWrapper;

/**
 * Session Bean implementation class EventoBL
 */
@Stateless(name="SolicitudCreditoBL")
public class SolicitudCreditoBL implements SolicitudCreditoBLLocal {

	@EJB
	private SolicitudCreditoDALLocal solicitudCreditoDAL;
	
	@EJB
	private CodeudorDALLocal codeudorDAL;
	
	@EJB
	private SoporteDALLocal soporteDAL;
	
	@EJB
	private TipoCreditoDALLocal tipoCreditoDAL;
	
	@EJB
	private EstadoCreditoDALLocal estadoCreditoDAL;
	
    /**
     * Default constructor. 
     */
    public SolicitudCreditoBL() {}

	@Override
	public byte crear(SolicitudCredito solicitudCredito) throws SifeapException {
		try{
			List<Codeudor> listaCodeudores = null;
			if (solicitudCredito.getCodeudores() != null) {
				listaCodeudores = new ArrayList<Codeudor>(solicitudCredito.getCodeudores());
				solicitudCredito.setCodeudores(null);
			}
			
			List<Soporte> listaSoportes = null;
			if (solicitudCredito.getSoportes() != null) {
				listaSoportes = new ArrayList<Soporte>(solicitudCredito.getSoportes());
				solicitudCredito.setSoportes(null);
			}
			
			//Crea la solicitud
			solicitudCreditoDAL.crear(solicitudCredito);
	
			crearSoportes(solicitudCredito.getIdSolicitudCredito(), listaSoportes);
			
			//Crea los codeudores
			crearCodeudores(solicitudCredito, listaCodeudores);
			return 1;
		}catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public List<SolicitudCredito> buscarTodos() throws SifeapException {
		try{
			return solicitudCreditoDAL.buscarTodos();
		}catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public byte modificar(SolicitudCredito solicitudCredito) throws SifeapException {
		try {
			//Consulta los soportes de la solicitud
			List<Soporte> listaSoportes = soporteDAL.buscarSoportesSolicitudCredito(solicitudCredito.getIdSolicitudCredito());
			
			//Elimina los registros asociados
			boolean resultado = solicitudCreditoDAL.eliminarRegistrosAsociados(solicitudCredito.getIdSolicitudCredito());
			
			//Elimina los soportes
			if (resultado && listaSoportes != null) {
				for (Soporte soporte : listaSoportes) {
					soporteDAL.eliminar(soporte);
				}
			}
			
			List<Codeudor> listaCodeudores = null;
			if (solicitudCredito.getCodeudores() != null) {
				listaCodeudores = new ArrayList<Codeudor>(solicitudCredito.getCodeudores());
				solicitudCredito.setCodeudores(null);
			}
			
			listaSoportes = null;
			if (solicitudCredito.getSoportes() != null) {
				listaSoportes = new ArrayList<Soporte>(solicitudCredito.getSoportes());
				solicitudCredito.setSoportes(null);
			}

			//Modifica la solicitud
			solicitudCreditoDAL.modificar(solicitudCredito);
			
			//Crea los nuevos soportes
			crearSoportes(solicitudCredito.getIdSolicitudCredito(), listaSoportes);

			//Crea los codeudores
			crearCodeudores(solicitudCredito, listaCodeudores);
			return 1;
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public boolean eliminar(SolicitudCredito solicitudCredito) throws SifeapException {
		try {
			solicitudCreditoDAL.eliminar(solicitudCredito);
			return true;
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public SolicitudCredito buscar(Object id) throws SifeapException {
		try {
			return solicitudCreditoDAL.buscar(id);
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}
	
	@Override
	public boolean remover(SolicitudCredito solicitudCredito) throws SifeapException {
		try {
			solicitudCreditoDAL.remover(solicitudCredito);
			return true;
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}
	
	@Override
	public Double obtenerDeudaAsociado(String cedula) {
		return new CreditosBridge().totalDeuda(cedula);
	}
	
	@Override
	public Double obtenerAportesAsociado(String cedula) {
		AporteWrapper aporteWp = new AportesBridge().buscarAportesAsociado(cedula);
		if (aporteWp != null) {
			return aporteWp.getMontoAportes();
		}
		return null;
	}
	
	@Override
	public List<TipoCredito> buscarTiposCredito() throws SifeapException {
		try{
			return tipoCreditoDAL.buscarTodos();
		}catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public TipoCredito buscarTipoCredito(Object id) throws SifeapException {
		try {
			return tipoCreditoDAL.buscar(id);
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}
	
	@Override
	public List<EstadoCredito> buscarEstadosCredito() throws SifeapException {
		try{
			return estadoCreditoDAL.buscarTodos();
		}catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public EstadoCredito buscarEstadoCredito(Object id) throws SifeapException {
		try {
			return estadoCreditoDAL.buscar(id);
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public List<SolicitudCredito> buscarMisSolicitudes(SolicitudCreditoVO solicitudCreditoVo) throws SifeapException {
		try {
			return solicitudCreditoDAL.buscarSolicitudes(solicitudCreditoVo, true);
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}
	
	@Override
	public boolean cambiarEstadoSolicitud(long idSolicitudCredito, Long estadoCredito, String comentario) throws SifeapException {
		try {
			solicitudCreditoDAL.cambiarEstadoSolicitud(idSolicitudCredito, estadoCredito, comentario);
			return true;
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}

	@Override
	public List<SolicitudCreditoVO> buscarSolicitudesGestionadas(SolicitudCreditoVO solicitudCreditoVo) throws SifeapException {
		try {
			List<SolicitudCreditoVO> listaSolicitudesVo = null;
			List<SolicitudCredito> listaSolicitudes = solicitudCreditoDAL.buscarSolicitudes(solicitudCreditoVo, false);
			
			if (listaSolicitudes != null) {
				listaSolicitudesVo = new ArrayList<SolicitudCreditoVO>();
				SolicitudCreditoVO solCredVo;
				for (SolicitudCredito solicitudCredito : listaSolicitudes) {
					solCredVo = new SolicitudCreditoVO();
					
					//Debe buscar el vinculado por cedula
					solCredVo.setAsociado(new VinculadosBridge().buscarPorCedula(solicitudCredito.getVincedula()));
					
					solCredVo.setSolicitudCredito(solicitudCredito);
					listaSolicitudesVo.add(solCredVo);
				}
				
			}
			
			return listaSolicitudesVo;
		} catch (Exception e) {
			throw new SifeapException(e);
		}
	}
	
	@Override
	public void cambiarEstadoSolicitudes(List<SolicitudCreditoVO> listaSolicitudes) throws SifeapException {
		for (SolicitudCreditoVO solicitudCredito : listaSolicitudes) {
			
			//Evalua si el estado nuevo no es nulo y si el estado anterior es "En estudio"
			if (solicitudCredito.getNuevoEstado() != null && solicitudCredito.getSolicitudCredito().getEstadoscredito().getIdEstadoCredito() == 3) {
				if (solicitudCredito.getNuevoEstado() != 6) {
					solicitudCredito.getSolicitudCredito().setComentario(null);
				}
				cambiarEstadoSolicitud(solicitudCredito.getSolicitudCredito().getIdSolicitudCredito(), solicitudCredito.getNuevoEstado(), solicitudCredito.getSolicitudCredito().getComentario());
			}
		}
	}
	
	@Override
	public byte validarMontoSolicitado(SolicitudCredito solicitudCredito, VinculadoWrapper asociado) {
		byte resultado = 1; //Correcto

		if (asociado == null) {
			//Hace la consulta
			asociado = new VinculadosBridge().buscarPorCedula(solicitudCredito.getVincedula());
		}
		
		Double montoAportes = obtenerAportesAsociado(asociado.getCedula());
		
		if (montoAportes == null) montoAportes = 0d;

		if (solicitudCredito.getMontoSolicitado() > (montoAportes * 3)) {
			//Si el monto solicitado es mayor a 3 veces el salario, debe escoger por lo menos una garantia
			if (!(solicitudCredito.getDescripcionPrenda() != null && solicitudCredito.getDescripcionPrenda().trim().length() > 0)
					&& !(solicitudCredito.getDescripcionHipoteca() != null && solicitudCredito.getDescripcionHipoteca().trim().length() > 0)) {
				resultado = 3;
			}
		} else if (solicitudCredito.getMontoSolicitado() > montoAportes
				&& !(solicitudCredito.getCodeudores() != null && solicitudCredito.getCodeudores().size() > 0)) {
			//Si el monto solicitado es mayor al salario, debe escoger un codeudor
			resultado = 2;
		}

		return resultado;
	}
	
	private void crearSoportes(long idSolicitudCredito, List<Soporte> listaSoportes) throws SifeapException {
		if (listaSoportes != null) {
			for (Soporte soporte : listaSoportes) {
				try {
					//Llama el valor de la secuencia
					soporteDAL.crear(soporte);

					//Debe insertar en SOPORTESCREDITO
					solicitudCreditoDAL.asociarSoportesCredito(idSolicitudCredito, soporte.getIdSoporte());
				} catch (Exception e) {
					throw new SifeapException(e);
				}
			}
		}
	}
	
	private void crearCodeudores(SolicitudCredito solicitudCredito, List<Codeudor> listaCodeudores) throws SifeapException {
		List<Soporte> listaSoportes = null;
		if (listaCodeudores != null) {
			for (Codeudor codeudor : listaCodeudores) {
				try {
					codeudor.setSolicitudescredito(solicitudCredito);
					
					if (codeudor.getSoportes() != null) {
						listaSoportes = new ArrayList<Soporte>(codeudor.getSoportes());
						codeudor.setSoportes(null);
					}
					
					codeudorDAL.crear(codeudor);
					
					//Crea los soportes para el codeudor
					if (listaSoportes != null) {
						for (Soporte soporte : listaSoportes) {
							soporteDAL.crear(soporte);
							
							//Debe insertar en SOPORTESCODEUDOR
							solicitudCreditoDAL.asociarSoportesCodeudor(codeudor.getIdCodeudor(), soporte.getIdSoporte());
						}
					}
				} catch (Exception e) {
					throw new SifeapException(e);
				}
			}
		}
	}
}
